﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Remotion.Linq.Clauses;
using Remotion.Linq.Utilities;

namespace Gumini.JulaDB.Linq
{
    public class QueryPartsAggregator
    {
        private List<string> _fromParts = new List<string>();
        private List<string> _whereParts = new List<string>();
        private List<string> _orderByParts = new List<string>();

        public string SelectPart { get; set; }

        public bool IsDistinct { get; set; }

        public void AddFromPart(IQuerySource querySource)
        {
            // "TableName Alias"
            _fromParts.Add(string.Format("{0} {1}", GetEntityName(querySource), querySource.ItemName));
        }

        public void AddWherePart(string formatString, params object[] args)
        {
            _whereParts.Add(string.Format(formatString, args));
        }

        public void AddOrderByPart(string ordering, OrderingDirection direction)
        {
            _orderByParts.Add(String.Format("{0} {1}", ordering, direction == OrderingDirection.Asc ? "asc" : "desc"));
        }

        public string BuildString()
        {
            var sb = new StringBuilder();

            if (string.IsNullOrEmpty(SelectPart) || _fromParts.Count == 0)
                throw new InvalidOperationException("A query must have a select part and at least one from part.");

            sb.AppendFormat("select {0}{1}", IsDistinct ? "distinct " : String.Empty, SelectPart);
            sb.AppendFormat(" from {0}", SeparatedStringBuilder.Build(", ", _fromParts));

            if (_whereParts.Any())
                sb.AppendFormat(" where {0}", SeparatedStringBuilder.Build(" and ", _whereParts));

            if (_orderByParts.Any())
                sb.AppendFormat(" order by {0}", SeparatedStringBuilder.Build(", ", _orderByParts));

            return sb.ToString();
        }

        private string GetEntityName(IQuerySource querySource)
        {
            // we assume there is exact mapping between class and table names
            return querySource.ItemType.Name;
        }
    }
}